declare function clearTimeout(id: any): any
interface Cddtime extends _Time {
  duration: number
  everyDuration?: $everyDaration
  dateSeparator: string
  timeSeparator: string
  final?: null | Function
  finally: null | Function
  times: number
  date: any
  start: () => void
  stop: () => void
}
interface timeParams {
  duration?: number//函数执行的间隔，单位为毫秒
  everyDuration?: $everyDaration | undefined//间隔执行的函数，如果有
  dateSeparator?: string//日期的间隔符
  timeSeparator?: string//时间的间隔符
  final?: null | boolean | Function//执行完最后要执行的
  times?: number//执行次数
  date?: Date//date对象，默认是当前日期和时间
}
interface $everyDaration {
  (self?: _Time): any
}
class _Time {
  isRuning: boolean = false
  private _id: any
  private _$date: any = ''//保存初次传入的时间
  stamp: number = 0//时间戳
  hours: number = 0
  times = 60//timeout时的次数
  minutes: number = 0
  seconds: number = 0
  year: number = 1990
  month: number = 0
  day: number = 0
  duration: number = 1000
  private _dateSeparator: string = '-'//存储内部分隔符
  private _timeSeparator: string = ':'//存储内部分隔符
  date: string = ''
  time: string = ''
  ap: string = ''
  //方法
  everyDuration?: $everyDaration
  finally: any
  constructor({
    duration = 1000,
    everyDuration = undefined,
    dateSeparator = '-',
    timeSeparator = ':',
    final = null,
    times = 60,
    date = new Date()
  }: timeParams = {}) {
    this.init(date)
    this.times = times
    this.finally = final
    this.duration = duration
    this.everyDuration = everyDuration
    this.dateSeparator = dateSeparator
    this.timeSeparator = timeSeparator

  }

  private init(date: Date) {
    this.isRuning = false
    this._time = this._date = this._$date = date//初始化时间和日期
    this.stamp = this._date.getTime()
  }

  // 日期分割符
  get dateSeparator() {
    return this._dateSeparator
  }

  set dateSeparator(separator: string) {
    this._dateSeparator = separator
    this._date = this._$date
  }

  // 时间分隔符
  get timeSeparator() {
    return this._timeSeparator
  }

  set timeSeparator(separator: string) {
    // this._timeSeparator = separator
    this._time = this._$date
  }

  // 日期
  get _date(): any {
    return this._$date
  }

  set _date(date: any) {
    this.year = date.getFullYear()
    this.month = date.getMonth() + 1
    this.day = date.getDate()
    this.date = '' + this.year + this.dateSeparator + this.formNumber(this.month) + this.dateSeparator + this.formNumber(this.day)
  }

  // 时间
  get _time(): any {
    return this._$date.getTime()
  }

  // 更新时间
  set _time(date: any) {
    this.hours = date.getHours()
    this.minutes = date.getMinutes()
    this.seconds = date.getSeconds()
    this.ap = this.hours <= 12 ? 'AM' : 'PM'
    this.time = '' + this.formNumber(this.hours) + this.timeSeparator + this.formNumber(this.minutes) + this.timeSeparator + this.formNumber(this.seconds)
  }

  formNumber(num: number): string {
    return num < 10 ? '0' + num : '' + num
  }

  // 开始计时
  start() {
    this.isRuning = true
    this.interval()
  }
  // 暂停
  stop() {
    this.isRuning = false
    clearTimeout(this._id)
    console.log(`time is up.`)
  }

  // 静态方法
  static formatT(date: string) {
    return (new Date(Date.parse(date.split(' ').join('T')))).getTime()
  }
  get weekMap() {
    return new Map([
      [0, '日'],
      [1, '一'],
      [2, '二'],
      [3, '三'],
      [4, '四'],
      [5, '五'],
      [6, '六']
    ])
  }
  week(type?: string) {
    if (!type) {
      return this._date.getDay()
    } else {
      return this.weekMap.get(this._date.getDay())
    }
  }
  // 倒计时函数功能
  timeout() {
    let self: _Time = this
    let cd = this.everyDuration
    this.everyDuration = function () {
      if (self.times > 0) {
        self.times -= 1
        cd && (cd(self))
      } else {
        self.stop()
        self.finally && (self.finally(self))
      }
    }
    this.start()
  }

  // 主程序
  private interval = () => {
    let self = this
    if (this.isRuning) {
      this._time = this._date = this._$date = new Date()
      this.everyDuration && (this.everyDuration(this))
      this._id = setTimeout(() => {
        self.interval()
      }, self.duration);
    } else {
      clearTimeout(this._id)
    }
  }
}

export default _Time
export {
  Cddtime,
  timeParams
}
